/*
 * Dcm_UDS0x10.c
 *
 *  Created on: 2018-1-16
 *      Author: Shute
 */
#include "UDS.h"


/****************************************************************
	 UDS:DiagnosticSessionControl (10 hex) service
 ***************************************************************/
#if (STD_ON == DCM_UDS_SERVICE0X10_ENABLED)
/*******************************/
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
FUNC(Std_ReturnType, DCM_CODE)Dcm_UDS0x10(
		Dcm_OpStatusType OpStatus,
		uint8  ProtocolCtrlId,
		P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_VAR) ErrorCode)
{
   	uint8   MsgCtrlId;
    uint8 iloop;
	#if(STD_ON == DCM_SESSION_FUNC_ENABLED)
   	uint8   SesIndex;
   	uint8   Subfunction;
   	uint8   DspSessionRowNum;
   	uint8   TxChannelCtrlIndex;
   	uint8   TxChannelCfgIndex;
   	uint16  Offset;
   	boolean  Flag;
    P2CONST(Dcm_DspSessionRowType ,AUTOMATIC ,DCM_APPL_CONST) pDspSessionRow;
	#endif
	#if((STD_ON==DCM_SESSION_FUNC_ENABLED)||(STD_ON == DCM_SECURITY_FUNC_ENABLED) )
    Std_ReturnType  ret;
	#endif

   	/**************************************/
   #if(STD_ON == DCM_SESSION_FUNC_ENABLED)
   	/*session check,check whether the current session supports the request service*/
   	ret = DsdInternal_SesCheck(ProtocolCtrlId,SID_DIAGNOSTIC_SESSION_CONTROL);
   	if(E_NOT_OK == ret)
   	{
   		/****@req DCM-FUNR-073[DCM211]****/
   		/*the current session does not support the request service,send NRC = 0x7F*/
   		(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_SERVICENOTSUPPORTEDINACTIVESESSION);
   		DsdInternal_ProcessingDone(ProtocolCtrlId);
   		return E_NOT_OK;
   	}
   #endif

    /**************************************/
   #if(STD_ON == DCM_SECURITY_FUNC_ENABLED)
    /*security check,check whether the current security supports the request service*/
    ret = DsdInternal_SecurityCheck(ProtocolCtrlId,SID_DIAGNOSTIC_SESSION_CONTROL);
    if (E_NOT_OK == ret)
    {
        /****@req DCM-FUNR-074[DCM217]****/
        /*the current security does not support the request service,send NRC = 0x33*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_SECURITYACCESSDENIED);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }
   #endif

 	/*************************************/
    /*if the required protocol is configured,get the index of runtime datum*/
    MsgCtrlId =  Dcm_ProtocolCtrl[ProtocolCtrlId].MsgCtrlIndex;

    /*check the message length*/
    if (DCM_UDS0X10_REQ_DATA_LENGTH != Dcm_MsgCtrl[MsgCtrlId].MsgContext.ReqDataLen)
    {
        /*the length of massage is not correct,send NRC 0x13*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }

   #if(STD_OFF == DCM_SESSION_FUNC_ENABLED)
   	/*if the session function is disabled,send NRC 0x31*/
   	(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_REQUESTOUTOFRANGE);
   	DsdInternal_ProcessingDone(ProtocolCtrlId);
   	return E_NOT_OK;

   #else
   	Subfunction = Dcm_MsgCtrl[MsgCtrlId].Subfunction;
   	DspSessionRowNum = Dcm_DspCfg.pDcm_DspSession->DcmDspSessionRow_Num;
   	pDspSessionRow   = Dcm_DspCfg.pDcm_DspSession->pDcmDspSessionRow;
   	Flag = FALSE;

   	/*************************************************/
   	/*check whether the required session is configured*/
   	for(SesIndex=0;(SesIndex<DspSessionRowNum)&&(FALSE==Flag);SesIndex++)
   	{
   		if(Subfunction == (pDspSessionRow[SesIndex].DcmDspSessionLevel))
   		{
   			Flag = TRUE;
   		}
   	}
   	/*if not configured,send NRC 0x12*/
   	if(FALSE == Flag)
   	{
   		/*SWS_Dcm_00307*/
   		(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_SUBFUNCTIONNOTSUPPORTED);
   		DsdInternal_ProcessingDone(ProtocolCtrlId);
   		return E_NOT_OK;
   	}
	#endif

    #if(STD_ON == DCM_SESSION_FUNC_ENABLED)
    ret = DsdInternal_SubSesCheck(ProtocolCtrlId,SID_DIAGNOSTIC_SESSION_CONTROL);
    if(E_NOT_OK == ret)
    {
        /****SWS_Dcm_00616****/
        /*the current session does not support the request sub service,send NRC = 0x7E*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_SUBFUNCTIONNOTSUPPORTEDINACTIVESESSION);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }
    #endif

   	/**************************************/
   #if(STD_ON == DCM_SECURITY_FUNC_ENABLED)
   	/*security check,check whether the current security supports the request service*/
   	ret = DsdInternal_SubSecurityCheck(ProtocolCtrlId,SID_DIAGNOSTIC_SESSION_CONTROL);
   	if (E_NOT_OK == ret)
   	{
   		/****@req DCM-FUNR-074[DCM217]****/
   		/*the current security does not support the request service,send NRC = 0x33*/
   		(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_SECURITYACCESSDENIED);
   		DsdInternal_ProcessingDone(ProtocolCtrlId);
   		return E_NOT_OK;
   	}
   #endif

   	/*************************************************/

	#if((STD_ON==DCM_SESSION_FUNC_ENABLED)||(STD_ON == DCM_SECURITY_FUNC_ENABLED) )

   	if(0x02u == Subfunction)
   	{
   	   	ret = RTE_PreConditonCheck();

   	   	if(E_OK != ret)
   	   	{
   	   		(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_CONDITIONSNOTCORRECT);
   	   		DsdInternal_ProcessingDone(ProtocolCtrlId);
   	   		return E_NOT_OK;
   	   	}
   	}
   	else
   	{
   		/* empty */
   	}

	#endif

	/*assemble and send positive response*/
	SchM_Enter_Dcm(Dcm_SesCtrl);
	Dcm_SesCtrl.Dcm_NewSes = Subfunction;
	SchM_Exit_Dcm(Dcm_SesCtrl);
	SchM_Enter_Dcm(Dcm_MsgCtrl);
	SchM_Enter_Dcm(Dcm_Channel);
	TxChannelCtrlIndex = Dcm_MsgCtrl[MsgCtrlId].Dcm_TxCtrlChannelIndex;
	TxChannelCfgIndex = Dcm_ChannelCtrl[TxChannelCtrlIndex].Dcm_ChannelCfgIndex;
	Offset = (Dcm_DslCfg.pDcmChannelCfg)[TxChannelCfgIndex].offset;

    /*check program request*/
    for (iloop = 0;iloop < Dcm_DspCfg.pDcm_DspSession->DcmDspSessionRow_Num;iloop++)
    {
        if ((Subfunction == Dcm_DspCfg.pDcm_DspSession->
                pDcmDspSessionRow[iloop].DcmDspSessionLevel)
         && (Dcm_DspCfg.pDcm_DspSession->pDcmDspSessionRow[iloop].
                 DcmDspSessionForBoot != DCM_NO_BOOT))
        {
         /*Set ReProgramingRequest Flag*/
          ReProgramingRequest = TRUE;
         if ((Dcm_DspCfg.pDcm_DspSession->pDcmDspSessionRow[iloop].
                 DcmDspSessionForBoot == DCM_OEM_BOOT)
             || (Dcm_DspCfg.pDcm_DspSession->pDcmDspSessionRow[iloop].
                     DcmDspSessionForBoot == DCM_OEM_BOOT_RESPAPP))
         {
             /*the SchM_Switch_DcmEcuReset need have Std_ReturnType to check NRC 0x22*/
             /* By this mode switch the DCM informs the BswM to prepare the jump to the bootloader.*/
             ret = SchM_Switch_DcmEcuReset(RTE_MODE_DcmEcuReset_JUMPTOBOOTLOADER);/*[SWS_Dcm_00532]*/
             if (ret == E_NOT_OK)
             {
                 (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_CONDITIONSNOTCORRECT);
                 DsdInternal_ProcessingDone(ProtocolCtrlId);
             }
             if ((Dcm_DslCfg.pDcmDslProtocol->pDcmDslProtocolRow[ProtocolCtrlId].
                     DcmSendRespPendOnTransToBoot == FALSE)
                     && ((Dcm_DspCfg.pDcm_DspSession->pDcmDspSessionRow[iloop].
                             DcmDspSessionForBoot == DCM_OEM_BOOT) ||
						((Dcm_MsgCtrl[MsgCtrlId].MsgContext.MsgAddInfo.SuppressPosResponse == TRUE)
										&& (Dcm_DspCfg.pDcm_DspSession->pDcmDspSessionRow[iloop].
						                         DcmDspSessionForBoot == DCM_OEM_BOOT_RESPAPP))))
             {
                 ret = Dcm_SetProgConditions(OpStatus,&ProgConditions);/*[SWS_Dcm_00720]*/
                 if (ret == E_OK)
                 {
                     /* By this mode switch the DCM informs the BswM to jump to the bootloader.*/
                     (void)SchM_Switch_DcmEcuReset(RTE_MODE_DcmEcuReset_EXECUTE);/*[SWS_Dcm_00719]*/
                 }
                 else if (ret == E_NOT_OK)/*[SWS_Dcm_00715]*/
                 {
                     (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_CONDITIONSNOTCORRECT);
                     DsdInternal_ProcessingDone(ProtocolCtrlId);
                 }
                 else if (ret == DCM_E_PENDING)
                 {
                     Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
                     return ret;
                 }
                 else
                 {
                     /*idle*/
                 }
             }
         }
         else if ((Dcm_DspCfg.pDcm_DspSession->pDcmDspSessionRow[iloop].
                 DcmDspSessionForBoot == DCM_SYS_BOOT)
                 || (Dcm_DspCfg.pDcm_DspSession->pDcmDspSessionRow[iloop].
                         DcmDspSessionForBoot == DCM_SYS_BOOT_RESPAPP))
         {
             /*the SchM_Switch_DcmEcuReset need have Std_ReturnType to check NRC 0x22*/
             /* By this mode switch the DCM informs the BswM to prepare the jump to the bootloader.*/
             ret = SchM_Switch_DcmEcuReset(
                     RTE_MODE_DcmEcuReset_JUMPTOSYSSUPPLIERBOOTLOADER);/*[SWS_Dcm_00592]*/
             if (ret == E_NOT_OK)
             {
                 (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_CONDITIONSNOTCORRECT);
                 DsdInternal_ProcessingDone(ProtocolCtrlId);
             }
             if ((Dcm_DslCfg.pDcmDslProtocol->pDcmDslProtocolRow[ProtocolCtrlId].
                     DcmSendRespPendOnTransToBoot == FALSE)
                        && ((Dcm_DspCfg.pDcm_DspSession->pDcmDspSessionRow[iloop].
                                DcmDspSessionForBoot == DCM_SYS_BOOT) ||
						((Dcm_MsgCtrl[MsgCtrlId].MsgContext.MsgAddInfo.SuppressPosResponse == TRUE)
								&& (Dcm_DspCfg.pDcm_DspSession->pDcmDspSessionRow[iloop].
				                         DcmDspSessionForBoot == DCM_SYS_BOOT_RESPAPP))))
                {
                    ret = Dcm_SetProgConditions(OpStatus,&ProgConditions);/*[SWS_Dcm_00720]*/
                    if (ret == E_OK)
                    {
                        /* By this mode switch the DCM informs the BswM to jump to the bootloader.*/
                        (void)SchM_Switch_DcmEcuReset(RTE_MODE_DcmEcuReset_EXECUTE);/*[SWS_Dcm_00719]*/
                    }
                    else if (ret == E_NOT_OK)/*[SWS_Dcm_00715]*/
                    {
                        (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_CONDITIONSNOTCORRECT);
                        DsdInternal_ProcessingDone(ProtocolCtrlId);
                    }
                    else if (ret == DCM_E_PENDING)
                    {
                        Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
                        return ret;
                    }
                    else
                    {
                        /*idle*/
                    }
                }
         }
         else
         {
             /*idle*/
         }
         /*check send NCR 0x78 */
         if (Dcm_DslCfg.pDcmDslProtocol->pDcmDslProtocolRow[ProtocolCtrlId].
                 DcmSendRespPendOnTransToBoot == TRUE)
         {
             (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_RESPONSE_PENDING);
             DsdInternal_ProcessingDone(ProtocolCtrlId);
             return E_OK;
         }
         else
         {
             if ((Dcm_DspCfg.pDcm_DspSession->pDcmDspSessionRow[iloop].DcmDspSessionForBoot
                     != DCM_SYS_BOOT_RESPAPP)
                 && (Dcm_DspCfg.pDcm_DspSession->pDcmDspSessionRow[iloop].DcmDspSessionForBoot
                         != DCM_OEM_BOOT_RESPAPP))
             {
                 /*[SWS_Dcm_01178]In case the ModeDeclarationGroupPrototype DcmEcuReset
                    is switched to mode JUMPTOBOOTLOADER or
                    JUMPTOSYSSUPPLIERBOOTLOADER, the configuration parameter
                    DcmSendRespPendOnTransToBoot is set to FALSE and the configuration
                    parameter DcmDspSessionForBoot is set to DCM_OEM_BOOT_RESPAPP or
                    DCM_SYS_BOOT_RESPAPP , the Dcm shall initiate the final response*/
                 return E_OK;
             }
         }
        }
    }

    /* check tx data length */
    if((6u) > (Dcm_DslCfg.pDcmChannelCfg[TxChannelCfgIndex].Dcm_DslBufferSize))
    {
        /*Pdu length is bigger than buffer size,ignore the request message */
        (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_RESPONSETOOLONG);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }

	Dcm_Channel[Offset] = 0x50u;
	Dcm_Channel[Offset + 1u] = Subfunction;
	Dcm_Channel[Offset + 2u] = (uint8)(pDspSessionRow[SesIndex-1u].DcmDspSessionP2ServerMax >>8u);
	Dcm_Channel[Offset + 3u] = (uint8)(pDspSessionRow[SesIndex-1u].DcmDspSessionP2ServerMax);
	Dcm_Channel[Offset + 4u] = (uint8)(((pDspSessionRow[SesIndex-1u].DcmDspSessionP2StarServerMax) / 10u) >>8u);
	Dcm_Channel[Offset + 5u] = (uint8)((pDspSessionRow[SesIndex-1u].DcmDspSessionP2StarServerMax) / 10u);
	Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResMaxDataLen = 6u;
	Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResDataLen 	= 6u;
	Dcm_MsgCtrl[MsgCtrlId].MsgContext.pResData = &Dcm_Channel[Offset];
	SchM_Exit_Dcm(Dcm_Channel);
	SchM_Exit_Dcm(Dcm_MsgCtrl);

	SchM_Switch_DcmDiagnosticSessionControl(Dcm_SesCtrl.Dcm_NewSes);

	DsdInternal_ProcessingDone(ProtocolCtrlId);
	return  E_OK;

}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"

#endif
